package org.charles.zhifou.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.charles.zhifou.common.response.ResponseCodeEnum;
import org.charles.zhifou.constant.UserConstant;
import org.charles.zhifou.common.exception.ThrowUtils;
import org.charles.zhifou.mapper.UserMapper;
import org.charles.zhifou.model.entity.User;
import org.charles.zhifou.model.vo.LoginUserVO;
import org.charles.zhifou.service.UserService;
import org.charles.zhifou.common.utils.HttpContextUtils;
import org.springframework.stereotype.Service;


/**
* @author charles
* @description 针对表【user(用户)】的数据库操作Service实现
* @createDate 2024-08-06 09:11:36
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    @Resource
    private UserMapper userMapper;

    /**
     * 用户登录
     * @param user 用户信息
     * @return 登录用户信息
     */
    @Override
    public LoginUserVO userLogin(User user) {
        // 查询用户是否存在, 不存在则抛异常
        User loginUser = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUserAccount, user.getUserAccount())
                        .eq(User::getUserPassword, user.getUserPassword())
        );
        ThrowUtils.throwIf(loginUser == null, ResponseCodeEnum.PARAMS_ERROR, "用户不存在或密码错误");

        // 记录用户的登录态 (Session)
        HttpSession session = HttpContextUtils.getRequest().getSession();
        session.setAttribute(UserConstant.USER_LOGIN_STATE, loginUser);

        // 实体类转 VO 并返回
        return LoginUserVO.entityToVo(loginUser);
    }

    /**
     * 用户注销
     */
    @Override
    public Boolean userLogout() {
        // 获取 Session
        HttpSession session = HttpContextUtils.getRequest().getSession();

        // 判断当前用户是否已登录, 若未登录则抛异常
        User userLoginState = (User) session.getAttribute(UserConstant.USER_LOGIN_STATE);
        ThrowUtils.throwIf(userLoginState == null, ResponseCodeEnum.NOT_LOGIN_ERROR);

        // 移除登录态
        session.removeAttribute(UserConstant.USER_LOGIN_STATE);

        return true;
    }

    /**
     * 获取当前登录用户
     * @return 当前登录用户
     */
    @Override
    public User getLoginUser() {
        HttpSession session = HttpContextUtils.getRequest().getSession();

        // 若当前用户尚未登录则抛异常
        User user = (User)session.getAttribute(UserConstant.USER_LOGIN_STATE);
        ThrowUtils.throwIf(user == null, ResponseCodeEnum.NOT_LOGIN_ERROR);

        // 后面考虑加 Redis 缓存
        // // 这段逻辑属实没看懂 - session 存在但是数据库不存在?
        // long userId = user.getId();
        // user = this.getById(userId);
        // ThrowUtils.throwIf(user == null, ResponseCodeEnum.NOT_LOGIN_ERROR);

        return user;
    }

    /**
     * 添加用户 (注册用户同样采用此接口)
     * @param user 新建用户信息
     * @return 新建用户 id
     */
    @Override
    public Long saveUser(User user) {
        // 账户不能重复
        long accountCount = userMapper.selectCount(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUserAccount, user.getUserAccount())
        );
        ThrowUtils.throwIf(accountCount > 0, ResponseCodeEnum.PARAMS_ERROR, "此账号已存在");

        // 添加用户
        boolean saveResult = this.saveOrUpdate(user);
        ThrowUtils.throwIf(!saveResult, ResponseCodeEnum.OPERATION_ERROR, "数据库操作失败");

        // 返回新用户 id
        return user.getId();
    }

    /**
     * 添加用户 (注册用户同样采用此接口)
     * @param user 新建用户信息
     * @return 新建用户 id
     */
    @Override
    public Boolean updateUserById(User user) {
        // 除自己外, 账户不能重复
        long accountCount = userMapper.selectCount(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUserAccount, user.getUserAccount())
                        .ne(User::getId, user.getId())
        );
        ThrowUtils.throwIf(accountCount > 0, ResponseCodeEnum.PARAMS_ERROR, "此账号已存在");

        // 更新用户
        return this.updateById(user);
    }
}




